﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
using System.Xml;
using Microsoft.SharePoint;

namespace SPProfileData
{
    class Exporter
    {
        private static long start;
        private static long total;
        public static void Export(string url, string filename)
        {
            using (SPSite site = new SPSite(url))
            {
                UserProfileManager userProfileManager = new UserProfileManager(ServerContext.GetContext(site));
                total = userProfileManager.Count;
                Console.Out.WriteLine("Profiles to export: {0}", total);

                XmlDocument xml = new XmlDocument();
                XmlNode root = xml.CreateNode(XmlNodeType.Element, "ProfileDump", "");
                xml.AppendChild(root);

                PropertyCollection properties = userProfileManager.Properties;
                var count = 0;
                start = DateTime.Now.Ticks;
                foreach (UserProfile userProfile in userProfileManager)
                {
                    count++;
                    if (count % 1000 == 0)
                    {
                        PrintProgress(count);
                    }
                    XmlNode user = xml.CreateNode(XmlNodeType.Element, "User", "");
                    XmlAttribute accountname = xml.CreateNode(XmlNodeType.Attribute, "AccountName", "") as XmlAttribute;
                    accountname.Value = userProfile["accountname"].ToString();
                    user.Attributes.Append(accountname);

                    foreach (Property prop in properties)
                    {
                        if (CanExport(prop, userProfile))
                        {
                            XmlNode p = xml.CreateNode(XmlNodeType.Element, "Property", "");
                            XmlAttribute name = xml.CreateNode(XmlNodeType.Attribute, "Name", "") as XmlAttribute;
                            XmlAttribute type = xml.CreateNode(XmlNodeType.Attribute, "Type", "") as XmlAttribute;
                            name.Value = prop.Name;
                            p.Attributes.Append(name);
                            p.Attributes.Append(type);

                            if (prop.ChoiceType.Equals(ChoiceTypes.Closed) || prop.ChoiceType.Equals(ChoiceTypes.Open))
                            {
                                type.Value = "List";
                                foreach (var s in userProfile[prop.Name])
                                {
                                    XmlNode e = xml.CreateNode(XmlNodeType.Element, "Entry", "");
                                    e.InnerText = s.ToString();
                                    p.AppendChild(e);
                                }
                            }
                            else
                            {
                                type.Value = prop.Type;
                                p.InnerText = userProfile[prop.Name].Value.ToString();
                            }
                            user.AppendChild(p);
                        }
                    }
                    root.AppendChild(user);
                }
                xml.Save(filename);
                Console.Out.WriteLine("Done");
            }
        }

        private static void PrintProgress(int count)
        {
            var diff = DateTime.Now.Ticks - start;
            var remaining = total - count;

            var perEach = diff / count;
            var r = remaining * perEach;

            var remainingTime = new DateTime(DateTime.Now.Ticks + r);
            Console.Out.WriteLine("Processed {0} profiles. Estimated completion {1}", count, remainingTime.ToShortTimeString());
        }

        private static bool CanExport(Property prop, UserProfile userProfile)
        {
            bool exportable = userProfile[prop.Name].Value != null && !string.IsNullOrEmpty(userProfile[prop.Name].Value.ToString());
            exportable &= !prop.Name.Equals("UserProfile_GUID", StringComparison.InvariantCultureIgnoreCase);
            exportable &= !prop.Name.Equals("SID", StringComparison.InvariantCultureIgnoreCase);
            exportable &= !prop.Name.Equals("accountname", StringComparison.InvariantCultureIgnoreCase);
            return exportable;
        }
    }
}
